package com.connor.bs.plm.table;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;

public class CTMap extends DefaultTableModel implements CellSpan {
	protected int rowSize;
	protected int columnSize;
	protected int[][][] span; // CellSpan

	@Override
	public int[] getSpan(int row, int column) {
		// TODO Auto-generated method stub
		if (isOutOfBounds(row, column)) {
			int[] ret_code = { 1, 1 };
			return ret_code;
		}
		return span[row][column];
	}

	@Override
	public void setSpan(int[] span, int row, int column) {
		// TODO Auto-generated method stub
		if (isOutOfBounds(row, column))
			return;
		this.span[row][column] = span;
	}

	@Override
	public boolean isVisible(int row, int column) {
		// TODO Auto-generated method stub
		if (isOutOfBounds(row, column))
			return false;
		if ((span[row][column][CellSpan.COLUMN] < 1) || (span[row][column][CellSpan.ROW] < 1))
			return false;
		return true;
	}

	@Override
	public void combine(int[] rows, int[] columns) {
		// TODO Auto-generated method stub

		int rowSpan = rows.length;
		int columnSpan = columns.length;
		int startRow = rows[0];
		int startColumn = columns[0];
		for (int i = 0; i < rowSpan; i++) {
			for (int j = 0; j < columnSpan; j++) {
				if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
						|| (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
					// System.out.println("can't combine");
					return;
				}
			}
		}
		for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
			for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
				span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
				span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
				// System.out.println("r " +ii +" c " +jj);
			}
		}
		span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
		span[startRow][startColumn][CellSpan.ROW] = rowSpan;
	}

	public void setSize(Dimension size) {
		columnSize = size.width;
		rowSize = size.height;
		span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
		initValue();
	}

	protected boolean isOutOfBounds(int row, int column) {
		if ((row < 0) || (rowSize <= row) || (column < 0) || (columnSize <= column)) {
			return true;
		}
		return false;
	}

	

	public void addRow() {

		Vector newData = new Vector(getColumnCount());
		dataVector.add(newData);

		//
		newRowsAdded(new TableModelEvent(this, getRowCount() - 1, getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
				TableModelEvent.INSERT));
		int[][][] oldSpan = span;
		int numRows = oldSpan.length;
		int numColumns = oldSpan[0].length;
		span = new int[numRows + 1][numColumns][2];
		System.arraycopy(oldSpan, 0, span, 0, numRows);
		for (int i = 0; i < numColumns; i++) {
			span[numRows][i][CellSpan.COLUMN] = 1;
			span[numRows][i][CellSpan.ROW] = 1;
		}
		rowSize = span.length;
	}
	public void addColumn(Object columnName) {

		int[][][] oldSpan = span;
		int numRows = oldSpan.length;
		int numColumns = oldSpan[0].length;
		span = new int[numRows][numColumns + 1][2];
		for (int i = 0; i < span.length; i++) {
			for (int j = 0; j < span[0].length; j++) {
				span[i][j][CellSpan.COLUMN] = 1;
				span[i][j][CellSpan.ROW] = 1;
			}
		}
		
		columnSize = span[0].length;
		addColumn(columnName, (Vector) null);
	}
	

	public void insertRow(int row) {
		Vector rowData = new Vector(getColumnCount());

		dataVector.insertElementAt(rowData, row);
		System.out.println("size:" + dataVector.size());

		//
		newRowsAdded(new TableModelEvent(this, row, row, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
		int[][][] newSpan = new int[span.length + 1][span[0].length][2];

		int numRows = span.length;
		int numColumns = span[0].length;
		for (int i = 0; i < newSpan.length; i++) {
			if (i < row) {
				for (int j = 0; j < numColumns; j++) {
					newSpan[i][j][0] = span[i][j][0];
					newSpan[i][j][1] = span[i][j][1];
				}
			} else if (i == row) {
				for (int j = 0; j < numColumns; j++) {
					newSpan[i][j][0] = 1;
					newSpan[i][j][1] = 1;
				}
			} else {
				for (int j = 0; j < numColumns; j++) {
					newSpan[i][j][0] = span[i - 1][j][0];
					newSpan[i][j][1] = span[i - 1][j][1];
				}
			}
		}
		span = newSpan;
		rowSize = span.length;
	}


	public CTMap(int numRows, int numColumns) {
		Vector names = new Vector(numColumns);
		names.setSize(numColumns);
		setColumnIdentifiers(names);
		dataVector = new Vector();
		setNumRows(numRows);
		setSize(new Dimension(numColumns, numRows));
	}

	protected void initValue() {
		System.out.println(span.length);
		for (int i = 0; i < span.length; i++) {
			for (int j = 0; j < span[i].length; j++) {
				span[i][j][CellSpan.COLUMN] = 1;
				span[i][j][CellSpan.ROW] = 1;
			}
		}
	}
	
	public void split(int row, int column) {
		if (isOutOfBounds(row, column))
			return;
		int columnSpan = span[row][column][CellSpan.COLUMN];
		int rowSpan = span[row][column][CellSpan.ROW];
		for (int i = 0; i < rowSpan; i++) {
			for (int j = 0; j < columnSpan; j++) {
				span[row + i][column + j][CellSpan.COLUMN] = 1;
				span[row + i][column + j][CellSpan.ROW] = 1;
			}
		}
	}
	
	public void removeCol() {

		columnIdentifiers.removeElementAt(columnIdentifiers.size()-1);
		dataVector.setSize(getRowCount());

        for (int i = 0; i < getRowCount()-1; i++) {
            
            ((Vector)dataVector.elementAt(i)).setSize(getColumnCount());
        }
		fireTableStructureChanged();
	}
}
